
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_gpio.h>


#include <linux/fs.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/uaccess.h>

#define printf(fmt, ...) printk(KERN_EMERG pr_fmt(fmt), ##__VA_ARGS__)
// 这个控制第二栈灯 亮了
// myleds{
// 	led1 = <&gpioe 10 0>; //gpioe10  0:default
// 	led2 = <&gpiof 10 0>; //gpiof10  0:default
//  led3 = <&gpioe 8 0>;  //gpioe8  0:default
// };

struct device_node *node;
int gpiono, gpiono1, gpiono2;
char kbuf[100] = "";
int ret;

#define CNAME "myleds"
int major;
struct device_node *node, *cnode, *enode;
int cno[3], eno[3];
char *name[] = {"led1", "led2", "led3"};
struct class *cls;
struct device *dev;

int myleds_open(struct inode *inode, struct file *file) {
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    return 0;
}

ssize_t mycdev_write(struct file *file,
                     const char __user *ubuf,
                     size_t size,
                     loff_t *offs) {
    // int ret;
    printk("%s:%s:%d\n", __FILE__, __func__, __LINE__);
    if (size > sizeof(kbuf))
        size = sizeof(kbuf);
    ret = copy_from_user(kbuf, ubuf, sizeof(kbuf));
    if (ret) {
        printk("copy data from user error\n");
        return -EIO;
    }
    printf("leds.c获取的入参 【%d】\n", kbuf[0]);
    if (kbuf[0] == 0) {
        printf("进入==0 里面\n");
        gpio_direction_output(gpiono, 0);
        gpio_direction_output(gpiono1, 0);
        gpio_direction_output(gpiono2, 0);
    }
    if (kbuf[0] == 1) {
        printf("进入==1 里面\n");
        gpio_direction_output(gpiono, 1);
        gpio_direction_output(gpiono1, 1);
        gpio_direction_output(gpiono2, 1);
    }

    return size;
}

struct file_operations fops = {
    .open = myleds_open,
    .write = mycdev_write,
    // .unlocked_ioctl = myleds_ioctl,
    // .release = myleds_close,
};

static int __init myleds_init(void) {
    major = register_chrdev(0, CNAME, &fops);
    if (major < 0) {
        printk("register chrdev error\n");
        goto ERR2;
    }
    // 4.创建设备节点
    cls = class_create(THIS_MODULE, CNAME);
    if (IS_ERR(cls)) {
        printk("class create error\n");
        ret = PTR_ERR(cls);
        goto ERR3;
    }
    dev = device_create(cls, NULL, MKDEV(major, 0), NULL, CNAME);
    if (IS_ERR(dev)) {
        printk("device create error\n");
        ret = PTR_ERR(dev);
        goto ERR4;
    }

    // int ret;
    // 1.解析到节点
    if ((node = of_find_node_by_path("/myleds")) == NULL) {
        printk("of_find_node_by_path error\n");
        return -ENODATA;
    }
    // 2.获取gpio号
    if ((gpiono = of_get_named_gpio(node, "led3", 0)) < 0) {
        printk("of_get_named_gpio error\n");
        return -ENODATA;
    }
    if ((gpiono1 = of_get_named_gpio(node, "led1", 0)) < 0) {
        printk("of_get_named_gpio error\n");
        return -ENODATA;
    }
    if ((gpiono2 = of_get_named_gpio(node, "led2", 0)) < 0) {
        printk("of_get_named_gpio error\n");
        return -ENODATA;
    }
    // 3.申请
    if ((ret = gpio_request(gpiono, NULL)) < 0) {
        printk("gpio_request error\n");
        return ret;
    }
    if ((ret = gpio_request(gpiono1, NULL)) < 0) {
        printk("gpio_request error\n");
        return ret;
    }
    if ((ret = gpio_request(gpiono2, NULL)) < 0) {
        printk("gpio_request error\n");
        return ret;
    }
    // 4.设置方向,设置电平状态
    // 三个灯都亮了
    gpio_direction_output(gpiono, 1);
    gpio_direction_output(gpiono1, 1);
    gpio_direction_output(gpiono2, 1);

    return 0;
ERR4:
    class_destroy(cls);
ERR3:
    unregister_chrdev(major, CNAME);
ERR2:
    return 0;
    // led_deinit();
ERR1:
    return ret;
}

static void __exit myleds_exit(void) {
    device_destroy(cls, MKDEV(major, 0));
    class_destroy(cls);
    unregister_chrdev(major, CNAME);

    gpio_free(gpiono);
    gpio_free(gpiono1);
    gpio_free(gpiono2);

    // led_deinit();
}

module_init(myleds_init);
module_exit(myleds_exit);
MODULE_LICENSE("GPL");